package com.dotandmedia.action;

import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;

import com.dotmedia.dboperations.PermissionDatabaseOperations;
import com.dotmedia.dboperations.RoleDatabaseOperations;
import com.dotmedia.dboperations.RolePermissionDatabaseOperations;
import com.dotmedia.dboperations.SystemDatabaseOperations;
import com.dotmedia.entities.Permission;
import com.dotmedia.entities.Role;
import com.dotmedia.entities.RolePermission;
import com.dotmedia.entities.SystemEntity;
import com.opensymphony.xwork2.ActionSupport;

/**
 * This action adds a new role to the database
 * 
 * @author siddharthsaha
 * 
 */
public class AddNewRoleAction extends ActionSupport implements SessionAware, ServletRequestAware, ServletResponseAware {

	private static Logger logger = Logger.getLogger("AddNewRoleAction");
	private static String ROLE_ALREADY_EXISTS = "role.already.exist";

	// the parameters
	private String roleDescription;
	private String roleNotes;
	private String roleExternalId;
	private String systemId; // this will be the system ext id
	private String[] permissionIds;

	protected Map session;
	protected HttpServletRequest request;
	protected HttpServletResponse response;

	@Override
	public void setServletResponse(HttpServletResponse resp) {
		this.response = resp;
	}

	@Override
	public void setServletRequest(HttpServletRequest req) {
		this.request = req;
	}

	@Override
	public void setSession(Map session) {
		this.session = session;
	}

	public String getRoleDescription() {
		return roleDescription;
	}

	public void setRoleDescription(String roleDescription) {
		this.roleDescription = roleDescription;
	}

	public String getRoleNotes() {
		return roleNotes;
	}

	public void setRoleNotes(String roleNotes) {
		this.roleNotes = roleNotes;
	}

	public String getRoleExternalId() {
		return roleExternalId;
	}

	public void setRoleExternalId(String roleExternalId) {
		this.roleExternalId = roleExternalId;
	}

	public String getSystemId() {
		return systemId;
	}

	public void setSystemId(String systemId) {
		this.systemId = systemId;
	}

	public String[] getPermissionIds() {
		return permissionIds;
	}

	public void setPermissionIds(String[] permissionIds) {
		this.permissionIds = permissionIds;
	}

	/**
	 * This method adds a new role into the database.
	 * 
	 * @return
	 */
	public String addNewRole() {
		logger.info("IN method addNewRole() in AddNewRoleAction");
		Enumeration parameterNames = request.getParameterNames();
		int permissionIdIndex = 0;
		if (permissionIds == null) {
			while (parameterNames.hasMoreElements()) {
				String currentParameterName = (String) parameterNames.nextElement();
				if (currentParameterName.equals("permissionIds[]")) {
					String[] values = request.getParameterValues(currentParameterName);
					permissionIds = new String[values.length];
					for (String value : values) {
						permissionIds[permissionIdIndex] = value;
						permissionIdIndex++;
					}
				}
			}
		}
		logger.info("Role external id obtained: " + getRoleExternalId());
		logger.info("Role description obtained: " + getRoleDescription());
		logger.info("Role notes obtained: " + getRoleNotes());
		logger.info("System id obtained: " + getSystemId());
		logger.info("Permissions obtained - ");
		for (int permissionIndex = 0; permissionIndex < permissionIds.length; permissionIndex++) {
			logger.info(permissionIds[permissionIndex]);
		}
		// now we need to add the role to the database
		// first check whether the role ext id already exists or not
		RoleDatabaseOperations roleDatabaseOperations = new RoleDatabaseOperations();
		List<Role> rolesObtained = roleDatabaseOperations.getRoleEntitiesWithExtId(getRoleExternalId());
		boolean roleAlreadyExists = false;
		for (int rolesObtainedIndex = 0; rolesObtainedIndex < rolesObtained.size(); rolesObtainedIndex++) {
			Role currentRole = rolesObtained.get(rolesObtainedIndex);
			if (currentRole.getRoleExtId().equals(getRoleExternalId())) {
				logger.warn("A role with the roleExtId " + getRoleExternalId() + " already exists");
				roleAlreadyExists = true;
				break;
			}
		}
		if (roleAlreadyExists) {
			logger.info("OUT method addNewRole() in AddNewRoleAction");
			return ROLE_ALREADY_EXISTS;
		} else {
			// we have to add this role
			// get the system entity for the systemExtId
			SystemDatabaseOperations systemDatabaseOperations = new SystemDatabaseOperations();
			List<SystemEntity> systemEntityObtained = systemDatabaseOperations.getSystemEntitiesWithExtId(getSystemId());
			SystemEntity targetSystemEntity = null;
			for (int systemIndex = 0; systemIndex < systemEntityObtained.size(); systemIndex++) {
				SystemEntity currentSystemEntity = systemEntityObtained.get(systemIndex);
				if (currentSystemEntity.getSystemExtId().equals(getSystemId())) {
					logger.info("Got the system entity with the systemExtId: " + getSystemId());
					targetSystemEntity = currentSystemEntity;
					break;
				}
			}
			if (targetSystemEntity != null) {
				Role addRole = new Role(getRoleExternalId(), getRoleDescription(), getRoleNotes(), targetSystemEntity);
				logger.info("Goint to persist new role into the database");
				roleDatabaseOperations.persistRoleEntity(addRole);
				logger.info("Persisted the new role into the database");
				// now we also have to add into RolePermission
				for (int permissionIndex = 0; permissionIndex < permissionIds.length; permissionIndex++) {
					String currentPermissionId = permissionIds[permissionIndex];
					logger.info("Adding for the permission id: " + currentPermissionId);
					PermissionDatabaseOperations permissionDatabaseOperations = new PermissionDatabaseOperations();
					List<Permission> permissionsObtained = permissionDatabaseOperations.getPermissionEntitiesWithExtId(currentPermissionId);
					Permission targetPermission = null;
					for (int permissionsObtainedIndex = 0; permissionsObtainedIndex < permissionsObtained.size(); permissionsObtainedIndex++) {
						Permission currentPermission = permissionsObtained.get(permissionsObtainedIndex);
						if (currentPermission.getPermissionExtId().equals(currentPermissionId)) {
							targetPermission = currentPermission;
							break;
						}
					}
					if (targetPermission != null) {
						logger.info("Permission found with the permission ext id: " + currentPermissionId);
						RolePermission addRolePermission = new RolePermission(addRole, targetPermission, targetSystemEntity);
						RolePermissionDatabaseOperations rolePermissionDatabaseOperations = new RolePermissionDatabaseOperations();
						logger.info("Persisting role permission with role_permission_id: " + addRolePermission.getId());
						rolePermissionDatabaseOperations.persistRolePermissionEntity(addRolePermission);
						logger.info("Persisted role permisison with role_permission_id: " + addRolePermission.getId());
					} else {
						logger.error("Permission not found with the permission ext id: " + currentPermissionId);
						// remove the added role
						roleDatabaseOperations.removeRoleEntity(addRole);
					}
				}
			} else {
				logger.error("Cannot find the system entity with the systemExtId: " + getSystemId());
				logger.info("OUT method addNewRole() in AddNewRoleAction");
				return ERROR;
			}
		}
		logger.info("OUT method addNewRole() in AddNewRoleAction");
		return SUCCESS;
	}

}
